using Gee;
using Gtk;
using Meridian.Data;
using Meridian.Side.Recovery;

namespace Meridian.Side {

public class SideStore : TreeStore {
    private TreeIter bookmark_root;
    private TreeIter history_root;
    private TreeIter download_root;
    
    private Map<int, Bookmark> bookmarks = new HashMap<int, Bookmark> ();
    private Map<int, Download> downloads = new HashMap<int, Download> ();
    private Map<int, History> histories = new HashMap<int, History> ();
    
    private Dao dao;
    
    public SideStore () {
        Type[] types = new Type[1];
        Type type = typeof (string);
        types[0] = type;
        set_column_types (types);
        this.dao = new Dao (); 
    }
    
    public void recover () {
        print ("Recovering bookmarks\n");       
        this.bookmark_root = load_category ("Bookmarks");
        foreach (Bookmark bookmark in new BookmarkFactory (dao).recover ()) {
            var iter = load_item (bookmark, this.bookmark_root);
            this.bookmarks.set (iter.stamp, bookmark);
        }
        
        print ("Recovering downloads\n");       
        this.download_root = load_category ("Downloads");
        foreach (Download download in new DownloadFactory (dao).recover ()) {
            var iter = load_item (download, this.download_root);
            this.downloads.set (iter.stamp, download);
        }
        
        print ("Recovering history\n");       
        this.history_root = load_category ("History");
        foreach (History history in new HistoryFactory (dao).recover ()) {
            var iter = load_item (history, this.history_root);
            this.histories.set (iter.stamp, history);
        }
    }
    
    private TreeIter load_category (string title) {
        TreeIter category_root;
        append (out category_root, null);
        set (category_root, 0, title);
        return category_root;
    }
    
    private TreeIter load_item (SideItem item, TreeIter category_root) {
        TreeIter index;
        append (out index, category_root);
        set (index, 0, item.title);
        
        return index;
    }
    
    private TreeIter insert_item (SideItem item, TreeIter category_root) {
        TreeIter index;
        print ("Inserting item [" + item.to_string () + "]");
        insert (out index, category_root, 0);
        set (index, 0, item.title);
        print ("Persisting item [" + item.to_string () + "]");
        item.persist (this.dao);
        
        return index;
    }
    
    public void store_bookmark (Bookmark bookmark) {      
        var iter = insert_item (bookmark, this.bookmark_root);
        this.bookmarks.set (iter.stamp, bookmark);
    }
    
    public void store_download (Download download) {      
        var iter = insert_item (download, this.download_root);
        this.downloads.set (iter.stamp, download);
    }
    
    public void store_history (History history) {      
        var iter = insert_item (history, this.history_root);
        this.histories.set (iter.stamp, history);
    }
    
}
}